﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms; // for the startup path, bad i know

using TranscoderSharp;

namespace TranscoderSharp.Coders
{
    public class Lame : Coder, CoderInterface
    {
        static string appLame = Path.Combine(Application.StartupPath, "lame.exe ");
        static string appMP3Val = Path.Combine(Application.StartupPath, "mp3val.exe");

        public static string Extension
        {
            get
            {
                return ".mp3";
            }
        }

        #region CoderInterface Members

        string CoderInterface.DecodeToWav(AudioFile InputAudioFile)
        {
            StringBuilder sb = new StringBuilder();

            string TempInputFilePath = InputAudioFile.TempFilePath;
            InputAudioFile.CopyToTempFile();
            string TempOutputFilePath = GetTempWavPath();
            
            sb.Append(" --decode ");
            sb.Append("\"" + TempInputFilePath + "\"");
            sb.Append(" ");
            sb.Append("\"" + TempOutputFilePath + "\"");

            if (!ValidateMp3(TempInputFilePath, InputAudioFile.Timeout))
                FixMp3(TempInputFilePath, InputAudioFile.Timeout);

            Transcoder.CallExternalProgram(appLame, sb.ToString(), 5);

            InputAudioFile.Status = AudioFile.EncodingStatus.Decoded;

            // delete temporary input file
            File.Delete(TempInputFilePath);
            // mp3val sometimes creates .bak files and doesn't delete them
            if (File.Exists(TempInputFilePath + ".bak"))
                File.Delete(TempInputFilePath + ".bak");

            return TempOutputFilePath;
        }

        void CoderInterface.EncodeWav(AudioFile AudioFile, string WaveFilePath, ConfigObject ConfigObject)
        {
            StringBuilder sb = new StringBuilder();

            string ConfigString = (ConfigObject as LameConfig).GetConfigString();
            string OutputPath = AudioFile.GetOutputFilePath(
                ConfigObject.OutputDirectory, ".mp3", ConfigObject.OutputFormatPath);

            sb.Append(ConfigString);
            sb.Append(" ");
            sb.Append("\"" + WaveFilePath + "\"");
            sb.Append(" ");
            sb.Append("\"" + OutputPath + "\"");

            int ExitCode = Transcoder.CallExternalProgram(appLame, sb.ToString(), 10);

            if (ExitCode != 0)
            {
                // an error has occured
                AudioFile.Status = AudioFile.EncodingStatus.Error;

                StreamWriter sw = new StreamWriter(@"c:\errors.log");
                sw.Write(sb.ToString());
                sw.Close();

                throw new Exception("Lame exited with " + ExitCode.ToString() + " when trying to " +
                    "encode " + AudioFile.FilePath + ".  Lame arguments : " + sb.ToString());
            }

            AudioFile.Status = AudioFile.EncodingStatus.Encoded;
        }

        #endregion

        #region mp3 val functions

        internal static void FixMp3(string FilePath, int Timeout)
        {
            Transcoder.CallExternalProgramWithOutput(appMP3Val, "-f \"" + FilePath + "\"", Timeout);
        }

        internal static bool ValidateMp3(string FilePath, int Timeout)
        {
            string output = Transcoder.CallExternalProgramWithOutput(appMP3Val, "\"" + FilePath + "\"", Timeout);
            return !output.Contains("WARNING:");
        }

        #endregion


        //private string GetTempMp3Path(AudioFile InputAudioFile)
        //{
        //    InputAudioFile.CopyToTempFile();
        //    return InputAudioFile.TempFilePath;
        //}
    }
}
